import java.util.ArrayList;
import java.util.TreeSet;

import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;

public class PolRangeQuery {
	/*范围处理方法*/
	private ArrayList<String> searchGeohash(double X1,double Y1,double X2,double Y2) throws ParseException{
		double lonlength;
		double latlength;
		double l;
		double y,x;
		int level;
		if(X1<X2){
			lonlength=X2-X1;
		}
		else {
			lonlength=X2-X1+360;
		}
		latlength=Y2-Y1;
		if(lonlength>=latlength){
			l=(2*Math.floor(Logarithm.log(360/lonlength, 2))-1);		
			y=180/(Math.pow(2, (l+1)/2));			
			if(latlength<=y){
				level=(int) (l+1);
			}
			else {
				level=(int) l;
			}
		}
		else{
			l=2*Math.floor(Logarithm.log(180/latlength, 2));
			x=360/(Math.pow(2, (l+2)/2));
			if(lonlength<=x){
				level=(int) (l+1);
			}
			else{
				level=(int) l;
			}
		}
		GeometryFactory geometryFactory=new GeometryFactory();
		WKTReader reader = new WKTReader(geometryFactory);
		String rangePol="POLYGON(("+String.valueOf(X1)+" "+String.valueOf(Y1)+","+" "+String.valueOf(X1)+" "+String.valueOf(Y2)+","+" "+String.valueOf(X2)+" "+String.valueOf(Y2)+","+" "+String.valueOf(X2)+" "+String.valueOf(Y1)+","+" "+String.valueOf(X1)+" "+String.valueOf(Y1)+"))";
		Polygon polygon = (Polygon) reader.read(rangePol);
		Geohash geohash=new Geohash();
		String leftDown=geohash.encodeMaxlevel(Y1, X1, level);
		String leftUp=geohash.encodeMaxlevel(Y2, X1,level);
		String rightUp=geohash.encodeMaxlevel(Y2, X2, level);
		String rightDown=geohash.encodeMaxlevel(Y1, X2, level);
		TreeSet<String> tr = new TreeSet<String>();
		tr.add(leftDown);
		tr.add(leftUp);
		tr.add(rightUp);
		tr.add(rightDown);
		String [] geoStrings=new String[tr.size()];
		for(int i=0;i<geoStrings.length;i++){
			geoStrings[i]=tr.pollFirst();
		}
//		System.out.println(level);
		for(int i=0;i<geoStrings.length;i++){
			if(TreeTest.Choose(polygon, geoStrings[i])){
				divRange(geoStrings[i],polygon,level);
			}			
		}
		return TreeTest.rangearrayList;		
	}
	private void divRange(String string,Polygon polygon,int level) throws ParseException {
		TreeNode root=new TreeNode();
		root=TreeTest.createTree(root,string,TreeTest.MAXSEARCHLEVEL);
		TreeTest test=new TreeTest();
		test.geohashSearchFunc(polygon,root,level);
	}
	/*基于模拟面数据的范围查询*/
	public ArrayList<String> indexRangeQueryTest(double X1,double Y1,double X2,double Y2) throws Exception{
		ArrayList<String> rangeArray=new ArrayList<String>();
		ArrayList<String> arrayList=new ArrayList<String>();
		/*查询范围处理，得到一组近似于查询范围的geohash值*/
		rangeArray=new PolRangeQuery().searchGeohash(X1, Y1, X2, Y2);
		HBaseSQLDriverTest test=new HBaseSQLDriverTest();
		/*在索引表中匹配这一系列geohash值geoStrings*/
		for(int i=0;i<rangeArray.size();i++){			
			String like=rangeArray.get(i);
			ArrayList<String> List=new ArrayList<String>();
			List=test.query("select geometry.getvalue from MONIINDEX where rowkey LIKE '"+like+"%'");
			arrayList.addAll(List);
		}
		TreeSet<String> treeSet=new TreeSet<String>();
		for(int i=0;i<arrayList.size();i++){
			String string=arrayList.get(i).substring(1,arrayList.get(i).length()-1);
			String []strings=string.split(", ");
			for(int j=0;j<strings.length;j++){
				treeSet.add(strings[j]);
			}
		}
		String [] geoStrings=new String[treeSet.size()];
		for(int i=0;i<geoStrings.length;i++){
			geoStrings[i]=treeSet.pollFirst();
		}
		long startTime2 = System.currentTimeMillis();
		/*二次过滤，之前得到一组在近似查询范围内的面数据，现在在存储表中查询到它们的坐标
		 * 构建成Geometry，用Geotools中的方法比较他们是否相交，若相交则加入最终结果集*/
		ArrayList<String> indexResult=new ArrayList<String>();
		GeometryFactory geometryFactory=new GeometryFactory();
	    WKTReader reader = new WKTReader( geometryFactory );
	    String rangeString="POLYGON(("+String.valueOf(X1)+" "+String.valueOf(Y1)+","+" "+String.valueOf(X1)+" "+String.valueOf(Y2)+","+" "+String.valueOf(X2)+" "+String.valueOf(Y2)+","+" "+String.valueOf(X2)+" "+String.valueOf(Y1)+","+" "+String.valueOf(X1)+" "+String.valueOf(Y1)+"))";
		Polygon rangePol = (Polygon) reader.read(rangeString);
		System.out.println("在查询范围内的数据数:"+geoStrings.length);
		for(int i=0;i<geoStrings.length;i++){
			String coordinate=test.query("select geometry.getvalue from pol where rowkey='"+geoStrings[i]+"'").get(0);
			Polygon multiPolygon=(Polygon) reader.read(coordinate);
		    	 if(rangePol.intersects(multiPolygon)){
		    		 indexResult.add(geoStrings[i]);
		    }
		}
		System.out.println("符合相交条件的数据数："+indexResult.size());
		long endTime2 = System.currentTimeMillis();
		System.out.println("程序二次过滤时间："+(endTime2-startTime2)+"ms");
		return indexResult;
	}
	public static void main(String args[]) throws Exception{
		long startTime = System.currentTimeMillis();
		RangeQuery rangeQuery=new RangeQuery();
		for(int i=0;i<100;i++){
			ArrayList<String> result=new ArrayList<String>();
			double X=FictitiousPolgon.getRandomNum(-180, 178);
			double Y=FictitiousPolgon.getRandomNum(-90, 88);
			result=rangeQuery.indexRangeQueryTest(X, Y, X+2, Y+2);
			TreeTest.rangearrayList.clear();
		}
		long endTime = System.currentTimeMillis();
		System.out.println("基于索引表运行时间："+(endTime-startTime)/100+"ms");
	}
}
